package com.ssy.lingxi.settle.accounts.handler.listener;

import com.rabbitmq.client.Channel;
import com.ssy.lingxi.dto.model.constant.SettleAccountsConstant;
import com.ssy.lingxi.dto.model.constant.SettleAccountQueueMessageTypeEnum;
import com.ssy.lingxi.dto.request.SettleAccountQueueDTO;
import com.ssy.lingxi.settle.accounts.service.IPlatformCouponSettlementService;
import com.ssy.lingxi.settle.accounts.service.ISettlementOrderService;
import com.ssy.lingxi.settle.accounts.utils.SerialNumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * 消息队列监听类
 * @author 侯鹏飞
 * @version 2.0.0
 * @date 2021-12-16
 */
@Component
public class MessageQueueListener {

    private final static Logger logger = LoggerFactory.getLogger(MessageQueueListener.class);


    @Resource
    private ISettlementOrderService orderService;

    @Resource
    private IPlatformCouponSettlementService platformCouponSettlementService;

    /**
     * 结算保存待对账单订单商品信息结果异步通知
     * @param message 消息
     * @param channel  消息通道
     */
    @RabbitListener(queues = SettleAccountsConstant.SA_AUTO_RECONCILIATION_QUEUE, ackMode = "MANUAL")
    public void settlementOrderHandler(Message message, Channel channel){

        try {
            orderService.saveToBeReconciliation(new String(message.getBody()));
            //确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
        } catch (Exception e) {
            logger.error("从消息队列接收结算订单商品消息错误：" + e.getMessage());
        }
    }

    /**
     * 结算服务处理标准队列
     * @param message 消息
     * @param channel 消息通道
     */
    @RabbitListener(queues = SettleAccountsConstant.SETTLE_ACCOUNT_BASE_QUEUE, ackMode = "MANUAL")
    public void baseHandler(Message message, Channel channel) {
        try {
            // step1: 获取消息体
            String jsonMessage = new String(message.getBody());
            logger.info("内部标准队列接收到消息 => " + jsonMessage);
            SettleAccountQueueDTO messageBean = SerialNumberUtils.deserializeObject(jsonMessage, SettleAccountQueueDTO.class);
            if (!Optional.ofNullable(messageBean)
                    .map(SettleAccountQueueDTO::getType)
                    .isPresent()) {
                logger.info("内部标准队列消息反序列化后错误 => " + jsonMessage);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                return;
            }
            // step2: 根据消息类型处理对应业务
            SettleAccountQueueMessageTypeEnum messageType = SettleAccountQueueMessageTypeEnum.parse(messageBean.getType());
            switch (messageType) {
                case TO_RECONCILIATION:
                    orderService.saveToBeReconciliation(messageBean.getMessage());
                    break;
                case PLATFORM_COUPON_SETTLEMENT:
                    platformCouponSettlementService.save(messageBean.getMessage());
                    break;
                default:
                    break;
            }
            // step3: 确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);

        } catch (Exception e) {
            logger.error("内部标准队列接收消息错误：" + e.getMessage());
        }
    }
}
